import * as vscode from 'vscode';
import { DeviceFileManager, DeviceFile } from './deviceFileManager';
import { DeviceConnectionManager, ConnectionState } from './deviceConnectionManager';
import * as path from 'path';

export class DeviceExplorerProvider implements vscode.TreeDataProvider<DeviceFile> {
    private _onDidChangeTreeData: vscode.EventEmitter<DeviceFile | undefined | null | void> = new vscode.EventEmitter<DeviceFile | undefined | null | void>();
    readonly onDidChangeTreeData: vscode.Event<DeviceFile | undefined | null | void> = this._onDidChangeTreeData.event;

    private connectionManager: DeviceConnectionManager;
    private fileManager: DeviceFileManager;
    private currentPath: string = '/';

    constructor(connectionManager: DeviceConnectionManager, fileManager: DeviceFileManager) {
        this.connectionManager = connectionManager;
        this.fileManager = fileManager;

        // Listen for connection state changes
        this.connectionManager.onStateChange((state) => {
            this.refresh();
            vscode.commands.executeCommand('setContext', 'micropython.deviceConnected', state === ConnectionState.CONNECTED);
        });
    }

    refresh(): void {
        this._onDidChangeTreeData.fire();
    }

    getTreeItem(element: DeviceFile): vscode.TreeItem {
        const treeItem = new vscode.TreeItem(
            element.name,
            element.isDirectory ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None
        );

        treeItem.tooltip = `${element.name} (${element.size || 0} bytes)`;
        treeItem.contextValue = element.isDirectory ? 'deviceDirectory' : 'deviceFile';

        if (!element.isDirectory) {
            treeItem.command = {
                command: 'micropython.openFile',
                title: 'Open File',
                arguments: [element]
            };

            // Set icon based on file extension
            const ext = path.extname(element.name).toLowerCase();
            switch (ext) {
                case '.py':
                    treeItem.iconPath = new vscode.ThemeIcon('file-code');
                    break;
                case '.txt':
                case '.md':
                    treeItem.iconPath = new vscode.ThemeIcon('file-text');
                    break;
                case '.json':
                    treeItem.iconPath = new vscode.ThemeIcon('file-code');
                    break;
                default:
                    treeItem.iconPath = new vscode.ThemeIcon('file');
            }
        } else {
            treeItem.iconPath = new vscode.ThemeIcon('folder');
        }

        return treeItem;
    }

    async getChildren(element?: DeviceFile): Promise<DeviceFile[]> {
        if (!this.connectionManager.isConnected) {
            return [];
        }

        try {
            const targetPath = element ? element.path : this.currentPath;
            const files = await this.fileManager.listFiles(targetPath);

            // Sort directories first, then files
            return files.sort((a, b) => {
                if (a.isDirectory && !b.isDirectory) return -1;
                if (!a.isDirectory && b.isDirectory) return 1;
                return a.name.localeCompare(b.name);
            });
        } catch (error) {
            vscode.window.showErrorMessage(`Failed to list files: ${error}`);
            return [];
        }
    }

    async navigateToPath(newPath: string): Promise<void> {
        this.currentPath = newPath;
        this.refresh();
    }

    getCurrentPath(): string {
        return this.currentPath;
    }
}

export class DeviceExplorerViewProvider {
    private treeDataProvider: DeviceExplorerProvider;
    private treeView: vscode.TreeView<DeviceFile>;

    constructor(connectionManager: DeviceConnectionManager, fileManager: DeviceFileManager) {
        this.treeDataProvider = new DeviceExplorerProvider(connectionManager, fileManager);

        this.treeView = vscode.window.createTreeView('micropythonDeviceExplorer', {
            treeDataProvider: this.treeDataProvider,
            showCollapseAll: true
        });

        this.treeView.onDidChangeSelection((e) => {
            if (e.selection.length > 0) {
                const selectedFile = e.selection[0];
                if (selectedFile.isDirectory) {
                    this.treeDataProvider.navigateToPath(selectedFile.path);
                }
            }
        });
    }

    refresh(): void {
        this.treeDataProvider.refresh();
    }

    reveal(file: DeviceFile): void {
        this.treeView.reveal(file);
    }

    dispose(): void {
        this.treeView.dispose();
    }
}
